#include "Item_Gene.h"
#include "Log.h"

Item_Gene::Item_Gene() {
    LOG_ENTER(OBJECT, "Item_Gene::Item_Gene");

    data = NULL;
    len = 0;

    LOG_EXIT();
}

Item_Gene::~Item_Gene() {
    LOG_ENTER(OBJECT, "Item_Gene::~Item_Gene");

    if (data != NULL)
        delete[] data;

    LOG_EXIT();
}

void Item_Gene::parse(Parser& parser,
                      const Metadata& fInfo,
                      std::string& name) {
    LOG_ENTER(OBJECT, "Item_Gene::parse");

    parser.next_line();
    std::string codes;
    parser.match_any_word(name);
    parser.match_any_word(codes);
    len = codes.length();
    data = new char[len+1];
    strcpy(data, codes.c_str());

    LOG_EXIT();
}

std::ostream& Item_Gene::print(std::ostream& os) const {
    LOG_ENTER(OBJECT, "Item_Gene::print");

    os << "[ ";
    for (int i=0; i<len; i++)
        os << data[i];
    os << " ]";


    LOG_EXIT();

    return os;
}

bool Item_Gene::operator==(const Metric_Object *other) const {
    LOG_ENTER(OBJECT, "Item_Gene::operator==");

    char *odata = ((Item_Gene*)other)->data;
    for (int i=0; i<len; i++) {
        if (data[i] != odata[i]) {

            LOG_EXIT();
            return false;
        }
    }

    LOG_EXIT();
    return true;
}

double Item_Gene::metric(const Metric_Object *other) const {
    LOG_ENTER(OBJECT, "Item_Gene::distance");

    char *odata = ((Item_Gene*)other)->data;
    int nDifferent = 0;
    int nMissing   = 0;
    for (int i=0; i<len; i++) {
        if (data[i] == '?' ||
            odata[i] == '?')
            nMissing++;
        else if (data[i] != odata[i])
            nDifferent++;
    }

    double result = nDifferent / (double)(len - nMissing);

    LOG_EXIT();
    return result;
}

std::ostream& operator<<( std::ostream& os,
                          const Item_Gene& g ) {
    return g.print(os);
}
